package com.ecarx.camera.worker.config;

import android.location.Location;
import android.util.ArraySet;

import androidx.annotation.FloatRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.ecarx.camera.constant.Constants;
import com.ecarx.camera.constant.SpConfig;
import com.ecarx.camera.utils.LogUtils;
import com.ecarx.camera.utils.SPUtils;

import java.util.Set;

public class ConfigManager {

    private static final String TAG = "ConfigManager";

    @Nullable
    private Location location;
    @Nullable
    private String locationDisplayedName;
    private float zoomRatio;
    private boolean modeVideo;
    private boolean usePhotoTimerCountdown;
    private boolean useVideoTimelapseMode;
    private boolean interiorVideoMuted, exteriorVideoMuted;
    private boolean isExteriorGeneralRecording;
    private long photoTimerCountdown;
    private boolean isPrivatePrivacyAgreed;
    private final Set<OnLocationChangedListener> onLocationChangedListenerSet;
    private final Set<OnLocationDisplayedNameChangedListener> onLocationDisplayedNameChangedListenerSet;
    private final Set<OnZoomRatioChangedListener> onZoomRatioChangedListenerSet;
    private final Set<OnModeChangedListener> onModeChangedListenerSet;
    private final Set<OnVideoMutedChangedListener> onVideoMutedChangedListenerSet;

    private static volatile ConfigManager instance = null;

    public static ConfigManager getInstance() {
        if (instance == null) {
            synchronized (ConfigManager.class) {
                if (instance == null) {
                    instance = new ConfigManager();
                }
            }
        }
        return instance;
    }

    private ConfigManager() {
        location = null;
        locationDisplayedName = null;
        zoomRatio = Constants.MIN_ZOOM_RATIO;
        modeVideo = false;
        usePhotoTimerCountdown = false;
        useVideoTimelapseMode = false;
        interiorVideoMuted = SPUtils.getInstance().getBoolean(SpConfig.BooleanKey.INTERIOR_VIDEO_MUTED, false);
        exteriorVideoMuted = SPUtils.getInstance().getBoolean(SpConfig.BooleanKey.EXTERIOR_VIDEO_MUTED, false);
        isExteriorGeneralRecording = SPUtils.getInstance().getBoolean(SpConfig.BooleanKey.EXTERIOR_GENERAL_RECORDING, false);
        photoTimerCountdown = SPUtils.getInstance().getLong(SpConfig.LongKey.PHOTO_TIMER_COUNTDOWN, Constants.PHOTO_TIMER_COUNTDOWN_3S);
        isPrivatePrivacyAgreed = SPUtils.getInstance().getBoolean(SpConfig.BooleanKey.PRIVATE_POLICY_HAS_AGREED, false);
        if (photoTimerCountdown != Constants.PHOTO_TIMER_COUNTDOWN_3S && photoTimerCountdown != Constants.PHOTO_TIMER_COUNTDOWN_5S) {
            setPhotoTimerCountdown(Constants.PHOTO_TIMER_COUNTDOWN_3S);
        }
        onLocationChangedListenerSet = new ArraySet<>();
        onLocationDisplayedNameChangedListenerSet = new ArraySet<>();
        onZoomRatioChangedListenerSet = new ArraySet<>();
        onModeChangedListenerSet = new ArraySet<>();
        onVideoMutedChangedListenerSet = new ArraySet<>();
    }

    @Nullable
    public Location getLocation() {
        return location;
    }

    @Nullable
    public String getLocationDisplayedName() {
        return locationDisplayedName;
    }

    public float getZoomRatio() {
        return zoomRatio;
    }

    public boolean isModeVideo() {
        return modeVideo;
    }

    public boolean isUsePhotoTimerCountdown() {
        return usePhotoTimerCountdown;
    }

    public boolean isUseVideoTimelapseMode() {
        return useVideoTimelapseMode;
    }

    public boolean isInteriorVideoMuted() {
        return interiorVideoMuted;
    }

    public boolean isExteriorVideoMuted() {
        return exteriorVideoMuted;
    }

    public boolean isExteriorGeneralRecording() {
        return isExteriorGeneralRecording;
    }

    public long getPhotoTimerCountdown() {
        return photoTimerCountdown;
    }

    public void setLocation(Location location) {
        if (location == null) {
            return;
        }
        this.location = location;
        for (OnLocationChangedListener onLocationChangedListener : onLocationChangedListenerSet) {
            onLocationChangedListener.onLocationChanged(this.location);
        }
    }

    public void setLocationDisplayedName(String locationDisplayedName) {
        this.locationDisplayedName = locationDisplayedName;
        for (OnLocationDisplayedNameChangedListener onLocationDisplayedNameChangedListener : onLocationDisplayedNameChangedListenerSet) {
            onLocationDisplayedNameChangedListener.onLocationDisplayedNameChanged(this.locationDisplayedName);
        }
    }

    public void setZoomRatio(@FloatRange(from = Constants.MIN_ZOOM_RATIO, to = Constants.MAX_ZOOM_RATIO) float zoomRatio) {
        this.zoomRatio = zoomRatio;
        for (OnZoomRatioChangedListener onZoomRatioChangedListener : onZoomRatioChangedListenerSet) {
            onZoomRatioChangedListener.onZoomRatioChanged(this.zoomRatio);
        }
    }

    public void setModeVideo(boolean modeVideo) {
        this.modeVideo = modeVideo;
        for (OnModeChangedListener onModeChangedListener : onModeChangedListenerSet) {
            onModeChangedListener.onModeChanged(this.modeVideo);
        }
    }

    public void setUsePhotoTimerCountdown(boolean usePhotoTimerCountdown) {
        this.usePhotoTimerCountdown = usePhotoTimerCountdown;
    }

    public void setUseVideoTimelapseMode(boolean useVideoTimelapseMode) {
        this.useVideoTimelapseMode = useVideoTimelapseMode;
    }

    public boolean setInteriorVideoMuted(boolean videoMuted) {
        boolean result = SPUtils.getInstance().put(SpConfig.BooleanKey.INTERIOR_VIDEO_MUTED, videoMuted, true);
        if (result) {
            this.interiorVideoMuted = videoMuted;
            for (OnVideoMutedChangedListener onVideoMutedChangedListener : onVideoMutedChangedListenerSet) {
                onVideoMutedChangedListener.onInteriorVideoMutedChanged(videoMuted);
            }
        }
        LogUtils.d(TAG, "setInteriorVideoMuted, videoMuted = [" + videoMuted + "], result = [" + result + "]");
        return result;
    }

    public boolean setExteriorVideoMuted(boolean videoMuted) {
        return setExteriorVideoMuted(videoMuted, true);
    }

    public boolean setExteriorVideoMuted(boolean videoMuted, boolean needCallback) {
        boolean result = SPUtils.getInstance().put(SpConfig.BooleanKey.EXTERIOR_VIDEO_MUTED, videoMuted, true);
        if (result) {
            this.exteriorVideoMuted = videoMuted;
            if (needCallback) {
                for (OnVideoMutedChangedListener onVideoMutedChangedListener : onVideoMutedChangedListenerSet) {
                    onVideoMutedChangedListener.onExteriorVideoMutedChanged(videoMuted);
                }
            }
        }
        LogUtils.d(TAG, "setExteriorVideoMuted, videoMuted = [" + videoMuted + "], result = [" + result + "]");
        return result;
    }

    public boolean setExteriorGeneralRecording(boolean isExteriorGeneralRecording) {
        boolean result = SPUtils.getInstance().put(SpConfig.BooleanKey.EXTERIOR_GENERAL_RECORDING, isExteriorGeneralRecording, true);
        if (result) {
            this.isExteriorGeneralRecording = isExteriorGeneralRecording;
        }
        LogUtils.d(TAG, "setExteriorGeneralRecording, [" + isExteriorGeneralRecording + "], result = [" + result + "]");
        return result;
    }

    public boolean setPhotoTimerCountdown(long photoTimerCountdown) {
        boolean result = SPUtils.getInstance().put(SpConfig.LongKey.PHOTO_TIMER_COUNTDOWN, photoTimerCountdown, true);
        if (result) {
            this.photoTimerCountdown = photoTimerCountdown;
        }
        LogUtils.d(TAG, "setPhotoTimerCountdown, photoTimerCountdown = [" + photoTimerCountdown + "], result = [" + result + "]");
        return result;
    }

    public boolean isPrivatePrivacyAgreed() {
        return isPrivatePrivacyAgreed;
    }

    public boolean setPrivatePrivacyAgreed(boolean isPrivatePrivacyAgreed) {
        boolean result = SPUtils.getInstance().put(SpConfig.BooleanKey.PRIVATE_POLICY_HAS_AGREED, isPrivatePrivacyAgreed, true);
        if (result) {
            this.isPrivatePrivacyAgreed = isPrivatePrivacyAgreed;
        }
        return result;
    }

    public boolean addOnLocationChangedListener(@NonNull OnLocationChangedListener onLocationChangedListener) {
        return onLocationChangedListenerSet.add(onLocationChangedListener);
    }

    public boolean removeOnLocationChangedListener(@NonNull OnLocationChangedListener onLocationChangedListener) {
        return onLocationChangedListenerSet.remove(onLocationChangedListener);
    }

    public boolean addOnLocationDisplayedNameChangedListener(@NonNull OnLocationDisplayedNameChangedListener onLocationDisplayedNameChangedListener) {
        return onLocationDisplayedNameChangedListenerSet.add(onLocationDisplayedNameChangedListener);
    }

    public boolean removeOnLocationDisplayedNameChangedListener(@NonNull OnLocationDisplayedNameChangedListener onLocationDisplayedNameChangedListener) {
        return onLocationDisplayedNameChangedListenerSet.remove(onLocationDisplayedNameChangedListener);
    }

    public boolean addOnZoomRatioChangedListener(@NonNull OnZoomRatioChangedListener onZoomRatioChangedListener) {
        return onZoomRatioChangedListenerSet.add(onZoomRatioChangedListener);
    }

    public boolean removeOnZoomRatioChangedListener(@NonNull OnZoomRatioChangedListener onZoomRatioChangedListener) {
        return onZoomRatioChangedListenerSet.remove(onZoomRatioChangedListener);
    }

    public boolean addOnModeChangedListener(@NonNull OnModeChangedListener onModeChangedListener) {
        return onModeChangedListenerSet.add(onModeChangedListener);
    }

    public boolean removeOnModeChangedListener(@NonNull OnModeChangedListener onModeChangedListener) {
        return onModeChangedListenerSet.remove(onModeChangedListener);
    }

    public boolean addOnVideoMutedChangedListener(@NonNull OnVideoMutedChangedListener onVideoMutedChangedListener) {
        return onVideoMutedChangedListenerSet.add(onVideoMutedChangedListener);
    }

    public boolean removeOnVideoMutedChangedListener(@NonNull OnVideoMutedChangedListener onVideoMutedChangedListener) {
        return onVideoMutedChangedListenerSet.remove(onVideoMutedChangedListener);
    }
}
